#pragma once

#include <cstdint> 
class CType;

// non-templated version of TForwardForwardLinkedListNode<T>, can force convert from/to TForwardForwardLinkedListNode<T>
class CReflectableForwardLinkedListNode
{
public:
	void* Data=nullptr;
	CReflectableForwardLinkedListNode* Next=nullptr;	

public:
    CReflectableForwardLinkedListNode()=default;

    CReflectableForwardLinkedListNode(CType* InType);

    //data will be copied
    CReflectableForwardLinkedListNode(CType* InType,void* InData);

    CReflectableForwardLinkedListNode(CType* InType,const CReflectableForwardLinkedListNode & Other);

    void* GetData() const;


    void Destroy(CType* InType);
    ~CReflectableForwardLinkedListNode();



};


class CReflectableForwardLinkedListIterator
{
protected:
    CReflectableForwardLinkedListNode * Node=nullptr;
public:
    CReflectableForwardLinkedListIterator(CReflectableForwardLinkedListNode * InNode);

    bool operator == (const CReflectableForwardLinkedListIterator& Other);
    bool operator != (const CReflectableForwardLinkedListIterator& Other);

    CReflectableForwardLinkedListIterator& operator++();

    CReflectableForwardLinkedListNode& operator*();
    CReflectableForwardLinkedListNode* operator->();
};

// non-templated version of TForwardForwardLinkedList<T>
class CReflectableForwardLinkedList
{
protected:
    uint64_t Size = 0;
	CReflectableForwardLinkedListNode* Head = nullptr;

public:
    CReflectableForwardLinkedList()=default;
    CReflectableForwardLinkedList(CType* InType,const CReflectableForwardLinkedList & Other );
    
    void Clear(CType* InType);

    void Destroy(CType* InType);
    ~CReflectableForwardLinkedList();

    bool Empty() const;

    void InsertAtHead(CReflectableForwardLinkedListNode* Node);


    CReflectableForwardLinkedListNode * PopNode();

    void RemoveNextNode(CType* InType, CReflectableForwardLinkedListNode* Node);
    void RemoveHead(CType* InType);

    CReflectableForwardLinkedListIterator begin() const;
    CReflectableForwardLinkedListIterator end() const;

    uint64_t GetHashCode(CType* InType) const;

    bool IsEqual(CType* InType,const CReflectableForwardLinkedList & Other) const;
};